jfblog

Random logs and notes

Some tests of argparse and configparser modules

Here are some notes on two modules of the standard library that can help to develop small scripts. The module argparse helps to parse the arguments to the script while the module configparser is useful for reading a particular textfile configuration.

Argparse examples

The argparse module of the standard library is designed to ease the parsing of arguments to a script, either mandatory or optional. Besides, it offers a unix like help ans documentation of the script interface.The documentation is available in https://docs.python.org/dev/library/argparse.html, together with a howto. A tutorial is also available in Python Module of the Week.

In [43]:
%%file argparse_tst.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#"""
#Created on July 19, 2014
#@author: bercherj
#"""

import argparse
import sys

whatitdoes="This program returns some interesting calculations."
myself="(c) JFB"
parser = argparse.ArgumentParser(description=whatitdoes, epilog=myself)

parser.add_argument(
# no option eg  '-o' '--output' --> positional argument
help = 'A number',
dest = 'num1',
default = 3,
type = int,
nargs = 1 # if '*' any number of arguments
)

parser.add_argument(
# no option eg  '-o' '--output' --> positional argument
help = 'A number',
dest = 'num2',
default = 3,
type = int,
nargs = 1 # if '*' any number of arguments
)

parser.add_argument('-o', dest='out', default=sys.stdout, 
                    help="optional output file", metavar='out-file', 
                    type=str)
# default=sys.stdout

parser.add_argument(
# no option eg  '-o' '--output' --> positional argument (no flag)
# but with a default value
help = 'A string',
dest = 'strarg',
default = 'Test',
type = str,
nargs = '?' # 0 or 1
)


parser.add_argument(
'-op',
'--operation',
help = 'An operation to apply to the two numbers',
dest = 'op',
default = 'add',
choices=('add','sub','mul','div','pow'),
action='store'
)

parser.add_argument(
'-f',
'--flag',
help = 'A flag',
dest = 'flag',
default = False,
action='store_true'
)

parser.add_argument(
'-v',
'--verbose',
help = 'Prints information',
dest = 'verbose',
default = False,
action='count'
)

def add(a,b): return a+b
def sub(a,b): return a-b
def mul(a,b): return a*b
def div(a,b): return a/b
def pow(a,b): return a**b

args = parser.parse_args()
op={'add':add, 'sub':sub, 'mul':mul, 'div':div, 'pow':pow}
op_string={'add':'addition', 'sub':'subtraction', 'mul':'multiplication', 
           'div':'division', 'pow':'power'}

verbose=args.verbose
out=open(args.out,"wt")
num1 = args.num1[0]
num2 = args.num2[0]

print("List of arguments: ", args, file=out)

if args.flag: 
    print("Flag f is set",file=out) 
else: 
    print("Flag f is not set",file=out)

if verbose: print("Computing the {0} of {1:d} and {2:d}".format(op_string[args.op],num1,num2),
                  file=out)
print("Result: ", op[args.op](num1,num2),file=out)
out.close()
Overwriting argparse_tst.py

In [44]:
%run argparse_tst -hIPython NotebookTest_argparse Last Checkpoint: Aug 05 22:39 (autosaved)
File
Edit
View
Insert
Cell
Kernel
Help
 Cell Toolbar:

title:  Some tests of argparse and configparser modules
slug: Argparse-configparser tests
date: 2014-08-05 22:12
tags: misc
comments: true
 
Here are some notes on two modules of the standard library that can help to develop small scripts. The module argparse helps to parse the arguments to the script while the module configparser is useful for reading a particular textfile configuration.
Argparse examples
The argparse module of the standard library is designed to ease the parsing of arguments to a script, either mandatory or optional. Besides, it offers a unix like help ans documentation of the script interface.The documentation is available in https://docs.python.org/dev/library/argparse.html, together with a howto. A tutorial is also available in Python Module of the Week.

%%file argparse_tst.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#"""
#Created on July 19, 2014
#@author: bercherj
#"""
 
import argparse
import sys
 
whatitdoes="This program returns some interesting calculations."
myself="(c) JFB"
parser = argparse.ArgumentParser(description=whatitdoes, epilog=myself)
 
parser.add_argument(
# no option eg  '-o' '--output' --> positional argument
help = 'A number',
dest = 'num1',
default = 3,
type = int,
nargs = 1 # if '*' any number of arguments
)
 
parser.add_argument(
# no option eg  '-o' '--output' --> positional argument
help = 'A number',
dest = 'num2',
default = 3,
type = int,
nargs = 1 # if '*' any number of arguments
)
 
parser.add_argument('-o', dest='out', default=sys.stdout, 
                    help="optional output file", metavar='out-file', 
                    type=str)
# default=sys.stdout
 
parser.add_argument(
# no option eg  '-o' '--output' --> positional argument (no flag)
# but with a default value
help = 'A string',
dest = 'strarg',
default = 'Test',
type = str,
nargs = '?' # 0 or 1
)
 
 
parser.add_argument(
'-op',
'--operation',
help = 'An operation to apply to the two numbers',
dest = 'op',
default = 'add',
choices=('add','sub','mul','div','pow'),
action='store'
)
 
parser.add_argument(
'-f',
'--flag',
help = 'A flag',
dest = 'flag',
default = False,
action='store_true'
)
 
parser.add_argument(
'-v',
'--verbose',
help = 'Prints information',
dest = 'verbose',
default = False,
action='count'
)
 
def add(a,b): return a+b
def sub(a,b): return a-b
def mul(a,b): return a*b
def div(a,b): return a/b
def pow(a,b): return a**b
 
args = parser.parse_args()
op={'add':add, 'sub':sub, 'mul':mul, 'div':div, 'pow':pow}
op_string={'add':'addition', 'sub':'subtraction', 'mul':'multiplication', 
           'div':'division', 'pow':'power'}
 
verbose=args.verbose
out=open(args.out,"wt")
num1 = args.num1[0]
num2 = args.num2[0]
 
print("List of arguments: ", args, file=out)
 
if args.flag: 
    print("Flag f is set",file=out) 
else: 
    print("Flag f is not set",file=out)
 
if verbose: print("Computing the {0} of {1:d} and {2:d}".format(op_string[args.op],num1,num2),
                  file=out)
print("Result: ", op[args.op](num1,num2),file=out)
out.close()
 
Overwriting argparse_tst.py

%run argparse_tst -h
usage: argparse_tst.py [-h] [-o out-file] [-op {add,sub,mul,div,pow}] [-f]
                       [-v]
                       num1 num2 [strarg]
usage: argparse_tst.py [-h] [-o out-file] [-op {add,sub,mul,div,pow}] [-f]
                       [-v]
                       num1 num2 [strarg]

This program returns some interesting calculations.

positional arguments:
  num1                  A number
  num2                  A number
  strarg                A string

optional arguments:
  -h, --help            show this help message and exit
  -o out-file           optional output file
  -op {add,sub,mul,div,pow}, --operation {add,sub,mul,div,pow}
                        An operation to apply to the two numbers
  -f, --flag            A flag
  -v, --verbose         Prints information

(c) JFB

In [45]:
%run argparse_tst 2 2 -op=add -vv -o=bibi.txt
In [46]:
cat bibi.txt
List of arguments:  Namespace(flag=False, num1=[2], num2=[2], op='add', out='bibi.txt', strarg='Test', verbose=2)
Flag f is not set
Computing the addition of 2 and 2
Result:  4

ConfigParser

It is also possible to load a prespecified configuration, using a config parser, like ConfigParser in the standard library. We give a simple example here, where we load a proxy configuration.

The proxy configuration

In [47]:
%%file proxies.cfg
[esiee]
http = http://cache.esiee.fr:3128/
https = http://cache.esiee.fr:3128/
[home]
http = http://proxy.domain.ext:3128/
https = http://proxy.domain.ext:3128/    
Writing proxies.cfg

In [57]:
%%file configparser_tst.py

import argparse

whatitdoes="This program tests the config parser."
myself="(c) JFB"
parser = argparse.ArgumentParser(description=whatitdoes, epilog=myself)

parser.add_argument('-v','--verbose',help = 'Prints information',
dest = 'verbose',default = False,action='store_true')

parser.add_argument('-p','-proxy','--proxy',
    help = 'Takes proxy configuration from "proxies.cfg"',
dest = 'proxy',default = None,action='store')

args = parser.parse_args()
print(args)

proxies={}
if args.proxy: # if the proxy option has been specified in the arguments
    import configparser
    config = configparser.ConfigParser()
    s=config.read('proxies.cfg')
    if s: #if the cfg file exists
        try:
           proxies=dict(config[args.proxy])
        except KeyError: # the specified key does not correspond to a section in the cfg file
            print("'%s' is not a valid key for a proxy section" % args.proxy)
    else:
        print("The config file proxies.cfg does not exist in current directory")    

print('proxies= ',proxies)
Overwriting configparser_tst.py

In [153]:
%run configparser_tst.py -h
usage: configparser_tst.py [-h] [-v] [-p PROXY]

This program tests the config parser.

optional arguments:
  -h, --help            show this help message and exit
  -v, --verbose         Prints information
  -p PROXY, -proxy PROXY, --proxy PROXY
                        Takes proxy configuration from "proxies.cfg"

(c) JFB

In [151]:
%run configparser_tst.py -p=zerg
Namespace(proxy='zerg', verbose=False)
'zerg' is not a valid key for a proxy section
proxies=  {}

In [152]:
%run configparser_tst.py -p=esiee
Namespace(proxy='esiee', verbose=False)
proxies=  {'http': 'http://cache.esiee.fr:3128/', 'https': 'http://cache.esiee.fr:3128/'}

A simple translation script

A funny example is the translation of a word given on the command line. For that, we use the http://glosbe.com/a-api API. The script makes use of - arguments on the command line, parsed with argparse - a configuration processed thanks to configparser - an internet connection

In [149]:
%%file translate_a_word.py
#author:jfb august 2014

import argparse
import urllib.parse
import urllib.request



### 1 ###  Script arguments and config ###################################
whatitdoes="This program translates a word from a language to another."
myself="(c) JFB"
parser = argparse.ArgumentParser(description=whatitdoes, epilog=myself)

parser.add_argument('-v','--verbose', help = 'Prints information',
dest = 'verbose',default = False, action='store_true')


parser.add_argument('-f','--from',help = 'translate from',dest = 'fro',
default = 'fr',choices=('en','de','fr','nl','es'),action='store')

parser.add_argument('-t','--to',help = 'translate to',dest = 'to',default = 'en',
choices=('en','de','fr','nl','es'),action='store')

parser.add_argument(help = 'word to translate',dest = 'word',default = 'hello',
nargs=1,action='store')

parser.add_argument('-p','-proxy','--proxy',
                    help = 'Takes proxy configuration from "proxies.cfg"',
dest = 'proxy',default = None,action='store')


args = parser.parse_args()

proxies={}
if args.proxy:
    import configparser
    config = configparser.ConfigParser()
    s=config.read('proxies.cfg')
    if s: #if the cfg file exists
        try:
           proxies=dict(config[args.proxy])
        except KeyError:
            print("'%s' is not a valid key for a proxy section" % args.proxy)
    else:
        print("The config file proxies.cfg does not exist in current directory")    

### 2 ### connects to the web service  ###################################
url = 'http://glosbe.com/gapi/translate'
values = {'from' : args.fro , 'dest' : args.to ,
              'format':'json' , 'phrase' : args.word[0] , 'pretty' : 'true', 'tm' : 'false'}
                       
proxy_handler = urllib.request.ProxyHandler(proxies)
opener = urllib.request.build_opener(proxy_handler)
response = opener.open(url+'/?'+urllib.parse.urlencode(values))
the_page = response.read().decode('latin1')
import json
page=json.loads(the_page)

### 3 ### Prints the translations  #########################################
# kind of result filtering
import html.parser
h = html.parser.HTMLParser()
for d in page['tuc']: 
    if 'phrase' in d.keys():
        if 'meanings' in d.keys(): 
            for k in range(len(d['meanings'])):
                 print(h.unescape(d['meanings'][k]['text']))
        print("-->",d['phrase']['text'])
Overwriting translate_a_word.py

For reference, we look at the dictionary obtained after page=json.loads(the_page)

In [148]:
page['tuc']
Out[148]:
[{'phrase': {'text': 'buenos dÃ\xadas', 'language': 'spa'},
  'authors': [1],
  'meaningId': 9170866376525822931,
  'meanings': [{'text': 'Saludo que se dice al encontrarse con alguien o al despedirse en la mañana.',
    'language': 'spa'},
   {'text': 'Salutation dite quand on se rencontre ou quand on se quitte le matin.',
    'language': 'fra'},
   {'text': 'Saludo que se utiliza durante el día.', 'language': 'spa'},
   {'text': 'Salutation dite dans la journée.', 'language': 'fra'}]},
 {'phrase': {'text': 'hola', 'language': 'spa'},
  'authors': [1],
  'meaningId': 3237975184227305932,
  'meanings': [{'text': 'Expresión de saludo utilizada entre dos o más personas de trato familiar.',
    'language': 'spa'},
   {'text': 'Expression de salutation utilisée entre deux personnes ou plus qui se rencontrent.',
    'language': 'fra'}]},
 {'phrase': {'text': 'buenas tardes', 'language': 'spa'},
  'authors': [2698],
  'meaningId': 8754367228613803561},
 {'phrase': {'text': 'buenas mañanas', 'language': 'spa'},
  'authors': [60172],
  'meaningId': 844651127364049044,
  'meanings': [{'text': 'Saludo que se dice al encontrarse con alguien o al despedirse en la mañana.',
    'language': 'spa'},
   {'text': 'Salutation dite quand on se rencontre ou quand on se quitte le matin.',
    'language': 'fra'}]},
 {'phrase': {'text': 'Buenas tardes', 'language': 'spa'},
  'authors': [2695],
  'meaningId': -7862237962244860629},
 {'phrase': {'text': 'buenos dias', 'language': 'spa'},
  'authors': [2697],
  'meaningId': -6184143237658615968},
 {'phrase': {'text': 'qué tal', 'language': 'spa'},
  'authors': [1],
  'meaningId': -9037967328194913728},
 {'phrase': {'text': 'saludo', 'language': 'spa'},
  'authors': [2692],
  'meaningId': 8882182478762943055},
 {'authors': [1796],
  'meaningId': None,
  'meanings': [{'text': 'gaîsuwa tsakanin mutun biyu ko daiwa daga asuba har zuwa tasawa rana',
    'language': 'fra'}]},
 {'authors': [2736],
  'meaningId': None,
  'meanings': [{'text': 'bonsoir (lorsque l’on s’adresse a une personne qui rentre)',
    'language': 'fra'}]},
 {'authors': [2736],
  'meaningId': None,
  'meanings': [{'text': 'bonjour (dans la journée)',
    'language': 'fra'}]},
 {'authors': [2736],
  'meaningId': None,
  'meanings': [{'text': 'bonjour (le matin)', 'language': 'fra'}]}]

And finally the test of the script

In [137]:
%run translate_a_word.py -h
usage: translate_a_word.py [-h] [-v] [-f {en,de,fr,nl,es}]
                           [-t {en,de,fr,nl,es}] [-p PROXY]
                           word

This program tests the config parser.

positional arguments:
  word                  word to translate

optional arguments:
  -h, --help            show this help message and exit
  -v, --verbose         Prints information
  -f {en,de,fr,nl,es}, --from {en,de,fr,nl,es}
                        translate from
  -t {en,de,fr,nl,es}, --to {en,de,fr,nl,es}
                        translate to
  -p PROXY, -proxy PROXY, --proxy PROXY
                        Takes proxy configuration from "proxies.cfg"

(c) JFB

and an actual translation

In [146]:
%run translate_a_word.py -f=fr -t=es  bonjour
Saludo que se dice al encontrarse con alguien o al despedirse en la mañana.
Salutation dite quand on se rencontre ou quand on se quitte le matin.
Saludo que se utiliza durante el día.
Salutation dite dans la journée.
--> buenos días
Expresión de saludo utilizada entre dos o más personas de trato familiar.
Expression de salutation utilisée entre deux personnes ou plus qui se rencontrent.
--> hola
--> buenas tardes
Saludo que se dice al encontrarse con alguien o al despedirse en la mañana.
Salutation dite quand on se rencontre ou quand on se quitte le matin.
--> buenas mañanas
--> Buenas tardes
--> buenos dias
--> qué tal
--> saludo

In [1]:
HTML(the_end(theNotebook))
Out[1]:

This post was written as an IPython notebook. It is available for download or as a static html.

Creative Commons License
jfblog by J.-F. Bercher is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
Based on a work at http://jfbercher.github.io/.

misc

Comments